package com.peanut.baby.http;

import com.peanut.baby.InitManager;
import com.peanut.baby.http.convert.AppGsonConvertFactory;
import com.peanut.baby.util.SignTools;
import com.peanut.devlibrary.LibContext;
import com.peanut.devlibrary.util.NetUtil;
import com.tencent.mars.xlog.Log;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

/**
 * Created by anonymouslystudio on 2017/6/6.
 */

public class RetrofitClient {
    private static final String TAG = RetrofitClient.class.getSimpleName();

    private static APIInterface retrofitService = new Retrofit.Builder()
            .baseUrl(HttpConfig.BASE_URL)
            .addConverterFactory(AppGsonConvertFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .client(getHttpClient())
            .build()
            .create(APIInterface.class);



    public static APIInterface getInstance(){
        return retrofitService;
    }

    private static OkHttpClient getHttpClient(){
        Cache cache = new Cache(new File(InitManager.getInstance().getCtx().getCacheDir(), "HttpCache"),
                1024 * 1024 * 50);
        OkHttpClient httpClient = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .cache(cache)
                .readTimeout(30, TimeUnit.SECONDS)
                .sslSocketFactory(SSLSocketClient.getSSLSocketFactory())
                .hostnameVerifier(SSLSocketClient.getHostnameVerifier())
                .addInterceptor(getCommParamsInterceptor())
                .addInterceptor(getLogInteceptor())
                .addInterceptor(getCacheInteceptor())
                .addInterceptor(getNetWorkInterceptor())
//                .addInterceptor(getDebugModeUrlIntercerptor())
                .build();
        return httpClient;
    }

    /**
     *
     * @return
     */
    private static Interceptor getNetWorkInterceptor (){
        return new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Log.d("TAG","getNetWorkInterceptor-> "+request.cacheControl().toString());
                Response response = chain.proceed(request);
                if (NetUtil.isNetworkAvailable(LibContext.getInstance().getContext())) {
                    response.newBuilder()
                            .removeHeader("Pragma")
                            .header("Cache-Control", request.cacheControl().toString())
                            .build();
                } else {
                    // 无网络时，设置超时为1周
                    int maxStale = 60 * 60 * 24 * 7;
                    response.newBuilder()
                            .removeHeader("Pragma")
                            .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                            .build();
                }
                return response;
            }
        };
    }

    /**
     * 缓存 没有网络时去取缓存
     * @return
     */
    private static Interceptor getCacheInteceptor(){
        return new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Log.d("TAG","getCacheInteceptor-> "+request.cacheControl().toString());
                if (!NetUtil.isNetworkAvailable(LibContext.getInstance().getContext())) {
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build();
                }else{
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_NETWORK)
                            .build();
                }
                return chain.proceed(request);
            }
        };
    }

    /**
     * 日志
     * @return
     */
    private static Interceptor getLogInteceptor(){
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        return logging;
    }

    /**
     *
     * @return
     */
    private static Interceptor getCommParamsInterceptor(){
        return new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Request.Builder requestBuilder = request.newBuilder();
                if(request.body() instanceof FormBody){
                    FormBody.Builder newFormBody = new FormBody.Builder();
                    FormBody oldFormBody = (FormBody) request.body();
                    for(int i = 0;i<oldFormBody.size();i++){
                        newFormBody.addEncoded(oldFormBody.encodedName(i),oldFormBody.encodedValue(i));
                    }
                    String sign = SignTools.createSign(oldFormBody);
                    Log.d(TAG,"sign: "+sign);
                    newFormBody.add("sign",sign);
                    requestBuilder.method(request.method(), newFormBody.build());
                }
                Request newRequest = requestBuilder.build();
               return chain.proceed(newRequest);
            }
        };
    }

    /**
     * intercerptor for baseUrl like 'schema://host:port/commonPath', if you don't want do like this
     * you can change in APIInterface, add all commonPath before post or get path , or you can remove all '/' before path
     * @return
     */
//    private static Interceptor getDebugModeUrlIntercerptor(){
//        return new Interceptor() {
//            @Override
//            public Response intercept(Chain chain) throws IOException {
//                Request request = chain.request();
//                Request.Builder requestBuilder = request.newBuilder();
//                if(BuildConfig.DEBUG){
//                    Log.d(TAG,"host "+request.url().host()+" port: "+request.url().port());
//                    HttpUrl originUrl = request.url();
//                    HttpUrl.Builder newBuilder = new HttpUrl.Builder()
//                            .scheme(originUrl.scheme())
//                            .host(originUrl.host())
//                            .port(originUrl.port());
//
//                    newBuilder.addEncodedPathSegment("peanuts");
//                    for (int i = 0; i < originUrl.pathSegments().size(); i++) {
//                        newBuilder.addEncodedPathSegment(originUrl.encodedPathSegments().get(i));
//                    }
//                    newBuilder.encodedPassword(originUrl.encodedPassword())
//                            .encodedUsername(originUrl.encodedUsername())
//                            .encodedQuery(originUrl.encodedQuery())
//                            .encodedFragment(originUrl.encodedFragment());
//                    HttpUrl newUrl = newBuilder.build();
//                    Request newRequest = requestBuilder.url(newUrl).build();
//                    return chain.proceed(newRequest);
//                }else{
//                    return chain.proceed(requestBuilder.build());
//                }
//
//            }
//        };
//    }

}
